package com.pai4j.zwiki.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.pai4j.zwiki.domain.entity.DetailedAnalysisReportEntity;
import com.pai4j.zwiki.domain.entity.ProjectAnalysisEntity;
import com.pai4j.zwiki.dto.ProjectAnalysisResponse;
import com.pai4j.zwiki.dto.ProjectSubmitRequest;
import com.pai4j.zwiki.repository.DetailedAnalysisReportRepository;
import com.pai4j.zwiki.repository.ProjectAnalysisRepository;
import com.pai4j.zwiki.service.agent.CodeReadingAgent;
import com.pai4j.zwiki.service.diagram.DiagramEnhancedService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 项目分析服务
 * 协调各个服务完成完整的项目分析流程
 *
 * @author pai4j
 * @since 2025-10-12
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ProjectAnalysisService {

    private final ProjectAnalysisRepository projectAnalysisRepository;
    private final DetailedAnalysisReportRepository detailedAnalysisReportRepository;
    private final GitRepositoryService gitRepositoryService;
    private final ZipFileService zipFileService;
    private final CodeAnalysisService codeAnalysisService;
    private final LLMService llmService;
    private final PlantUmlService plantUmlService;
    private final ThesisGenerationService thesisGenerationService;
    private final CodeReadingAgent codeReadingAgent;
    private final DiagramEnhancedService diagramEnhancedService;
    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 提交项目分析任务（GitHub URL方式）
     */
    @Transactional
    public ProjectAnalysisResponse submitProjectFromGitHub(ProjectSubmitRequest request) {
        log.info("提交GitHub项目分析任务: {}", request.getRepositoryUrl());

        // 参数验证（通过 @Valid 注解已经进行了基本验证，这里进行业务验证）
        if (request.getUserId() == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        if (request.getRepositoryUrl() == null || request.getRepositoryUrl().trim().isEmpty()) {
            throw new IllegalArgumentException("仓库URL不能为空");
        }
        
        // 验证仓库URL格式
        if (!gitRepositoryService.isValidRepositoryUrl(request.getRepositoryUrl())) {
            throw new IllegalArgumentException("无效的GitHub仓库URL格式");
        }

        // 创建分析任务
        String taskId = UUID.randomUUID().toString();
        ProjectAnalysisEntity entity = ProjectAnalysisEntity.builder()
                .taskId(taskId)
                .userId(request.getUserId())
                .projectName(request.getProjectName() != null && !request.getProjectName().trim().isEmpty() 
                    ? request.getProjectName() 
                    : gitRepositoryService.extractRepositoryName(request.getRepositoryUrl()))
                .repositoryUrl(request.getRepositoryUrl())
                .sourceType("github")
                .status("pending")
                .progress(0)
                .currentStep("等待开始")
                .hasCustomTemplate(request.getHasCustomTemplate() != null && request.getHasCustomTemplate())
                .build();

        projectAnalysisRepository.save(entity);

        // 异步执行分析
        executeAnalysisAsync(taskId);

        return convertToResponse(entity);
    }

    /**
     * 提交项目分析任务（ZIP上传方式）
     */
    @Transactional
    public ProjectAnalysisResponse submitProjectFromZip(
            ProjectSubmitRequest request,
            MultipartFile zipFile) {
        
        log.info("提交ZIP项目分析任务: {}", request.getProjectName());

        // 参数验证（通过 @Valid 注解已经进行了基本验证，这里进行业务验证）
        if (request.getUserId() == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        if (zipFile == null || zipFile.isEmpty()) {
            throw new IllegalArgumentException("ZIP文件不能为空");
        }
        
        // 验证ZIP文件
        if (!zipFileService.isValidZipFile(zipFile)) {
            throw new IllegalArgumentException("无效的ZIP文件格式");
        }

        // 创建分析任务
        String taskId = UUID.randomUUID().toString();
        ProjectAnalysisEntity entity = ProjectAnalysisEntity.builder()
                .taskId(taskId)
                .userId(request.getUserId())
                .projectName(request.getProjectName() != null && !request.getProjectName().trim().isEmpty()
                    ? request.getProjectName()
                    : zipFileService.extractProjectName(zipFile))
                .sourceType("zip")
                .status("pending")
                .progress(0)
                .currentStep("等待开始")
                .hasCustomTemplate(request.getHasCustomTemplate() != null && request.getHasCustomTemplate())
                .build();

        projectAnalysisRepository.save(entity);

        // 异步执行分析
        executeAnalysisAsync(taskId, zipFile);

        return convertToResponse(entity);
    }

    /**
     * 异步执行项目分析（GitHub方式）
     */
    @Async
    public void executeAnalysisAsync(String taskId) {
        try {
            ProjectAnalysisEntity entity = projectAnalysisRepository.findByTaskId(taskId)
                    .orElseThrow(() -> new RuntimeException("任务不存在"));

            // 1. 克隆代码
            updateProgress(taskId, "cloning", 10, "正在克隆代码仓库");
            String workspacePath = gitRepositoryService.cloneRepository(
                    entity.getRepositoryUrl(), taskId);
            entity.setWorkspacePath(workspacePath);
            projectAnalysisRepository.save(entity);

            // 执行后续分析
            executeAnalysisSteps(taskId, entity);

        } catch (Exception e) {
            log.error("项目分析失败: {}", taskId, e);
            handleAnalysisError(taskId, e);
        }
    }

    /**
     * 异步执行项目分析（ZIP方式）
     */
    @Async
    public void executeAnalysisAsync(String taskId, MultipartFile zipFile) {
        try {
            ProjectAnalysisEntity entity = projectAnalysisRepository.findByTaskId(taskId)
                    .orElseThrow(() -> new RuntimeException("任务不存在"));

            // 1. 解压ZIP文件
            updateProgress(taskId, "extracting", 10, "正在解压ZIP文件");
            String workspacePath = zipFileService.extractZipFile(zipFile, taskId);
            entity.setWorkspacePath(workspacePath);
            projectAnalysisRepository.save(entity);

            // 执行后续分析
            executeAnalysisSteps(taskId, entity);

        } catch (Exception e) {
            log.error("项目分析失败: {}", taskId, e);
            handleAnalysisError(taskId, e);
        }
    }

    /**
     * 执行分析步骤（优化版 - 改进错误处理和数据校验）
     */
    private void executeAnalysisSteps(String taskId, ProjectAnalysisEntity entity) {
        try {
            // 2. 代码分析
            updateProgress(taskId, "analyzing", 30, "正在分析代码结构");
            Map<String, Object> analysisResult = codeAnalysisService.analyzeProject(
                    entity.getWorkspacePath(), taskId);
            
            // 安全地提取分析结果（添加类型检查和默认值）
            entity.setTotalFiles(getIntValue(analysisResult, "totalFiles", 0));
            entity.setJavaFiles(getIntValue(analysisResult, "totalJavaFiles", 0));
            entity.setTotalLines(getLongValue(analysisResult, "totalLines", 0L));
            entity.setPrimaryLanguage("Java");
            projectAnalysisRepository.save(entity);

            // 3. 生成架构总结
            updateProgress(taskId, "analyzing", 50, "正在生成架构总结");
            Map<String, Object> projectInfo = new HashMap<>(analysisResult);
            projectInfo.put("projectName", entity.getProjectName());
            
            String architectureSummary = llmService.generateArchitectureSummary(projectInfo);
            
            // 检查架构总结是否生成成功
            if (architectureSummary == null || architectureSummary.trim().isEmpty() 
                || architectureSummary.contains("失败")) {
                log.warn("架构总结生成失败或为空，使用默认总结");
                architectureSummary = "项目架构总结生成中...";
            }

            // 4. 执行深度代码阅读（Agent多轮分析）
            updateProgress(taskId, "analyzing", 55, "正在执行深度代码阅读（多轮Agent分析）");
            Map<String, Object> deepAnalysisReport = codeReadingAgent.executeDeepReading(
                    taskId, entity.getWorkspacePath());
            
            // 保存详细分析报告（添加异常处理）
            saveDetailedAnalysisReport(taskId, deepAnalysisReport);

            // 5. 生成完整的架构图集合
            updateProgress(taskId, "generating", 65, "正在生成完整架构图集合");
            Map<String, String> allDiagrams = new HashMap<>();
            
            try {
                allDiagrams = diagramEnhancedService.generateAllDiagrams(taskId);
            } catch (Exception e) {
                log.error("生成增强架构图失败，使用基础图表", e);
            }
            
            // 同时保留原有的简单架构图（添加异常处理）
            try {
                String classDiagramPath = plantUmlService.generateClassDiagram(taskId);
                String archDiagramPath = plantUmlService.generateArchitectureDiagram(
                        taskId, architectureSummary);
                
                if (classDiagramPath != null && !classDiagramPath.isEmpty()) {
                    allDiagrams.put("simpleClassDiagram", classDiagramPath);
                }
                if (archDiagramPath != null && !archDiagramPath.isEmpty()) {
                    allDiagrams.put("simpleArchitectureDiagram", archDiagramPath);
                }
            } catch (Exception e) {
                log.error("生成基础架构图失败", e);
            }
            
            if (!allDiagrams.isEmpty()) {
                entity.setDiagramFilePath(String.join(",", allDiagrams.values()));
                projectAnalysisRepository.save(entity);
                
                // 更新详细报告的图表路径
                updateDetailedReportDiagrams(taskId, allDiagrams);
            }

            // 6. 生成论文
            updateProgress(taskId, "generating", 80, "正在生成毕业论文");
            String thesisPath = null;
            try {
                thesisPath = thesisGenerationService.generateThesis(
                        taskId, projectInfo, architectureSummary, allDiagrams, 
                        entity.getCustomTemplatePath());
                
                if (thesisPath != null && !thesisPath.isEmpty()) {
                    entity.setThesisFilePath(thesisPath);
                    projectAnalysisRepository.save(entity);
                }
            } catch (Exception e) {
                log.error("生成论文失败，但继续完成分析", e);
                // 论文生成失败不应该中断整个流程
            }

            // 7. 完成
            updateProgress(taskId, "completed", 100, "分析完成");
            entity.setStatus("completed");
            entity.setProgress(100);
            entity.setCompletedAt(LocalDateTime.now());
            projectAnalysisRepository.save(entity);

            log.info("项目分析完成: {}", taskId);

        } catch (Exception e) {
            log.error("执行分析步骤失败: {}", taskId, e);
            handleAnalysisError(taskId, e);
            // 重新抛出异常以触发事务回滚
            throw new RuntimeException("分析步骤执行失败", e);
        }
    }
    
    /**
     * 安全地获取 Integer 值
     */
    private Integer getIntValue(Map<String, Object> map, String key, Integer defaultValue) {
        Object value = map.get(key);
        if (value instanceof Integer) {
            return (Integer) value;
        } else if (value instanceof Number) {
            return ((Number) value).intValue();
        }
        return defaultValue;
    }
    
    /**
     * 安全地获取 Long 值
     */
    private Long getLongValue(Map<String, Object> map, String key, Long defaultValue) {
        Object value = map.get(key);
        if (value instanceof Long) {
            return (Long) value;
        } else if (value instanceof Number) {
            return ((Number) value).longValue();
        }
        return defaultValue;
    }

    /**
     * 更新分析进度（优化版 - 减少数据库查询，添加异常处理）
     */
    private void updateProgress(String taskId, String status, int progress, String step) {
        try {
            Optional<ProjectAnalysisEntity> optional = projectAnalysisRepository.findByTaskId(taskId);
            if (optional.isEmpty()) {
                log.error("更新进度失败：任务不存在: {}", taskId);
                return;
            }
            
            ProjectAnalysisEntity entity = optional.get();
            entity.setStatus(status);
            entity.setProgress(progress);
            entity.setCurrentStep(step);
            projectAnalysisRepository.save(entity);
            
            log.info("任务进度更新: {} - {}% - {}", taskId, progress, step);
        } catch (Exception e) {
            log.error("更新任务进度失败: {}", taskId, e);
            // 进度更新失败不应该中断分析流程
        }
    }

    /**
     * 处理分析错误
     */
    private void handleAnalysisError(String taskId, Exception e) {
        try {
            ProjectAnalysisEntity entity = projectAnalysisRepository.findByTaskId(taskId)
                    .orElse(null);
            
            if (entity != null) {
                entity.setStatus("failed");
                entity.setErrorMessage(e.getMessage());
                projectAnalysisRepository.save(entity);
            }
        } catch (Exception ex) {
            log.error("处理错误时发生异常", ex);
        }
    }

    /**
     * 查询分析任务状态
     */
    public ProjectAnalysisResponse getAnalysisStatus(String taskId) {
        ProjectAnalysisEntity entity = projectAnalysisRepository.findByTaskId(taskId)
                .orElseThrow(() -> new RuntimeException("任务不存在"));
        return convertToResponse(entity);
    }

    /**
     * 查询用户的所有分析任务
     */
    public List<ProjectAnalysisResponse> getUserAnalysisList(Long userId) {
        List<ProjectAnalysisEntity> entities = projectAnalysisRepository
                .findByUserIdOrderByCreatedAtDesc(userId);
        return entities.stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList());
    }

    /**
     * 保存详细分析报告（优化版 - 增强异常处理和数据校验）
     */
    @Transactional
    protected void saveDetailedAnalysisReport(String taskId, Map<String, Object> reportData) {
        if (reportData == null || reportData.isEmpty()) {
            log.warn("分析报告数据为空，跳过保存: {}", taskId);
            return;
        }
        
        try {
            DetailedAnalysisReportEntity report = DetailedAnalysisReportEntity.builder()
                    .taskId(taskId)
                    .projectOverview(safeToJson(reportData.get("overview")))
                    .coreModulesAnalysis(safeToJson(reportData.get("coreModules")))
                    .dependencyAnalysis(safeToJson(reportData.get("dependencies")))
                    .designPatterns(safeToJson(reportData.get("designPatterns")))
                    .qualityAnalysis(safeToJson(reportData.get("quality")))
                    .businessFlows(safeToJson(reportData.get("businessFlows")))
                    .techStack(safeToJson(reportData.get("techStack")))
                    .comprehensiveReport(safeGetString(reportData.get("comprehensiveReport")))
                    .deepReadingReport(safeToJson(reportData.get("deepReadingReport")))
                    .build();
            
            detailedAnalysisReportRepository.save(report);
            log.info("详细分析报告已保存, 任务ID: {}", taskId);
            
        } catch (Exception e) {
            log.error("保存详细分析报告失败，但不中断流程: {}", taskId, e);
            // 保存失败不应该中断整个分析流程，只记录错误
        }
    }
    
    /**
     * 安全地转换为 JSON 字符串
     */
    private String safeToJson(Object obj) {
        if (obj == null) {
            return "{}";
        }
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (Exception e) {
            log.warn("转换JSON失败，使用空对象", e);
            return "{}";
        }
    }
    
    /**
     * 安全地获取字符串值
     */
    private String safeGetString(Object obj) {
        if (obj == null) {
            return "";
        }
        return obj.toString();
    }

    /**
     * 更新详细报告的图表路径
     */
    @Transactional
    protected void updateDetailedReportDiagrams(String taskId, Map<String, String> diagrams) {
        try {
            Optional<DetailedAnalysisReportEntity> optional = detailedAnalysisReportRepository.findByTaskId(taskId);
            if (optional.isPresent()) {
                DetailedAnalysisReportEntity report = optional.get();
                report.setDetailedClassDiagramPath(diagrams.get("classDiagram"));
                report.setPackageDependencyPath(diagrams.get("packageDependency"));
                report.setCallChainPath(diagrams.get("callChain"));
                report.setLayerArchitecturePath(diagrams.get("layerArchitecture"));
                report.setModuleRelationPath(diagrams.get("moduleRelation"));
                report.setDependencyHeatmapData(diagrams.get("dependencyHeatmap"));
                detailedAnalysisReportRepository.save(report);
            }
        } catch (Exception e) {
            log.error("更新详细报告图表路径失败", e);
        }
    }

    /**
     * 获取详细分析报告
     */
    public DetailedAnalysisReportEntity getDetailedReport(String taskId) {
        return detailedAnalysisReportRepository.findByTaskId(taskId)
                .orElseThrow(() -> new RuntimeException("详细报告不存在"));
    }

    /**
     * 转换为响应DTO
     */
    private ProjectAnalysisResponse convertToResponse(ProjectAnalysisEntity entity) {
        return ProjectAnalysisResponse.builder()
                .taskId(entity.getTaskId())
                .projectName(entity.getProjectName())
                .status(entity.getStatus())
                .progress(entity.getProgress())
                .currentStep(entity.getCurrentStep())
                .primaryLanguage(entity.getPrimaryLanguage())
                .totalFiles(entity.getTotalFiles())
                .javaFiles(entity.getJavaFiles())
                .totalLines(entity.getTotalLines())
                .errorMessage(entity.getErrorMessage())
                .createdAt(entity.getCreatedAt())
                .completedAt(entity.getCompletedAt())
                .build();
    }
}

